#ifndef XTHREDSAFEQUEUE_HPP
#define XTHREDSAFEQUEUE_HPP
#include <list>
#include <condition_variable>
#include <mutex>
#include <functional>
#include<optional>

using namespace std;
template<typename T>
class XThrdSafeQueue{
public:
    XThrdSafeQueue(){
        m_mutex = new std::mutex;
        cv_isEmpty = new std::condition_variable;
    }
    ~XThrdSafeQueue(){
        delete m_mutex;
        delete cv_isEmpty;
    }

    XThrdSafeQueue(const XThrdSafeQueue& rths) = delete;
    XThrdSafeQueue& operator=(const XThrdSafeQueue& rths) = delete;

    XThrdSafeQueue(XThrdSafeQueue&& rths){
        this->m_messageQ = std::move(rths.m_messageQ);
        this->m_mutex = rths.m_mutex;
        this->cv_isEmpty = rths.cv_isEmpty;
        this->m_num = rths.m_num;
        rths.m_mutex = nullptr;
        rths.cv_isEmpty = nullptr;
        rths.m_num = 0;
    };

    XThrdSafeQueue& operator=(XThrdSafeQueue&& rths){
        this->m_messageQ = std::move(rths.m_messageQ);
        this->m_mutex = rths.m_mutex;
        this->cv_isEmpty = rths.cv_isEmpty;
        this->m_num = rths.m_num;
        rths.m_mutex = nullptr;
        rths.cv_isEmpty = nullptr;
        rths.m_num = 0;
        return *this;
    };

public:
template<typename MSG> 
void postmessge(MSG&& msg){
    std::unique_lock<mutex> lock(*m_mutex);
    m_messageQ.push_back(std::forward<MSG>(msg));
    m_num++;
    cv_isEmpty->notify_all();
}

std::optional<T> getMessageBlock(){
    unique_lock<mutex> lock(*m_mutex);
    cv_isEmpty->wait(lock, [this](){return m_num != 0;});  //简化代码书写

    T msg = std::move(m_messageQ.front());
    m_messageQ.pop_front();
    m_num--;
    return msg;
}

std::optional<T> getMessageNoBlock(int msec){
    unique_lock<mutex> lock(*m_mutex);
    bool status = cv_isEmpty->wait_for(lock, std::chrono::milliseconds(msec), [this]()
                                           { return m_num != 0; }); //简化代码书写
    if (status)
    {
        T msg = std::move(m_messageQ.front());
        m_messageQ.pop_front();
        m_num--;
        return msg;
    }else{
        return std::nullopt;    //若使用T作为反回值，return T(); T需要支持默认构造才行
    }
}

std::optional<T> getMessage(int msec = -1)
{
    if (msec == -1)
        return getMessageBlock();
    else
        return getMessageNoBlock(msec);
}

//应付1:右值可移动   2:有的对象不允许拷贝，只能移动
template<typename MSG> 
void sendmessage(MSG&& msg){
    std::unique_lock<mutex> lock(*m_mutex);
    m_messageQ.push_front(std::forward<MSG>(msg));
    m_num++;
    cv_isEmpty->notify_all();
}

private:
    list<T> m_messageQ;
    mutex *m_mutex = nullptr;
    condition_variable *cv_isEmpty = nullptr;
    uint32_t m_num = 0;
};
#endif